package com.cc.wechat.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cc.wechat.common.ResultCode;
import com.cc.wechat.common.constants.UserConstants;
import com.cc.wechat.common.constants.MessageConstants;
import com.cc.wechat.dto.request.PrivateMessageRequest;
import com.cc.wechat.entity.PrivateMessage;
import com.cc.wechat.entity.User;
import com.cc.wechat.exception.BusinessException;
import com.cc.wechat.mapper.PrivateMessageMapper;
import com.cc.wechat.mq.producer.MessageProducer;
import com.cc.wechat.service.MessageService;
import com.cc.wechat.service.UserService;
import com.cc.wechat.websocket.message.WebSocketMessage;
import com.cc.wechat.websocket.message.WebSocketMessageType;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 消息服务实现类
 */
@Service
@RequiredArgsConstructor
public class MessageServiceImpl extends ServiceImpl<PrivateMessageMapper, PrivateMessage> implements MessageService {

    private final UserService userService;
    private final MessageProducer messageProducer;

    /**
     * 发送私聊消息
     *
     * @param request 消息请求
     * @return 发送的消息
     */
    @Override
    @Transactional
    public PrivateMessage sendPrivateMessage(PrivateMessageRequest request) {
        // 1. 获取当前用户
        User currentUser = userService.getCurrentUser();
        Long currentUserId = currentUser.getId();

        // 2. 检查接收者是否存在
        User receiver = userService.getById(request.getReceiverId());
        if (receiver == null) {
            throw new BusinessException(ResultCode.USER_NOT_FOUND, UserConstants.Message.USER_NOT_FOUND);
        }

        // 3. 创建消息
        PrivateMessage message = new PrivateMessage();
        message.setSenderId(currentUserId);
        message.setReceiverId(request.getReceiverId());
        message.setContent(request.getContent());
        message.setType(request.getType());
        message.setStatus(0); // 0:未读
        save(message);

        // 4. 构建WebSocket消息
        WebSocketMessage<PrivateMessage> wsMessage = WebSocketMessage.<PrivateMessage>builder()
                .type(WebSocketMessageType.PRIVATE_MSG)
                .senderId(currentUserId)
                .receiverId(request.getReceiverId())
                .data(message)
                .timestamp(System.currentTimeMillis())
                .build();

        // 5. 发送WebSocket消息
        messageProducer.sendPrivateMessage(wsMessage);

        return message;
    }

    /**
     * 获取私聊消息
     *
     * @param friendId 好友ID
     * @param page 页码
     * @param size 每页大小
     * @return 消息分页列表
     */
    @Override
    public Page<PrivateMessage> getPrivateMessages(Long friendId, Integer page, Integer size) {
        // 1. 获取当前用户
        User currentUser = userService.getCurrentUser();
        Long currentUserId = currentUser.getId();

        // 2. 创建分页对象
        Page<PrivateMessage> pageParam = new Page<>(page, size);

        // 3. 查询消息记录
        return lambdaQuery()
                .and(wrapper -> wrapper
                        .and(w -> w
                                .eq(PrivateMessage::getSenderId, currentUserId)
                                .eq(PrivateMessage::getReceiverId, friendId))
                        .or(w -> w
                                .eq(PrivateMessage::getSenderId, friendId)
                                .eq(PrivateMessage::getReceiverId, currentUserId)))
                .orderByDesc(PrivateMessage::getCreatedAt)
                .page(pageParam);
    }

    /**
     * 标记消息为已读
     *
     * @param friendId 好友ID
     */
    @Override
    @Transactional
    public void markMessagesAsRead(Long friendId) {
        // 1. 获取当前用户
        User currentUser = userService.getCurrentUser();
        Long currentUserId = currentUser.getId();

        // 2. 更新未读消息状态
        lambdaUpdate()
                .eq(PrivateMessage::getReceiverId, currentUserId)
                .eq(PrivateMessage::getSenderId, friendId)
                .eq(PrivateMessage::getStatus, 0)
                .set(PrivateMessage::getStatus, 1)
                .update();

        // 3. 构建WebSocket消息
        WebSocketMessage<Long> wsMessage = WebSocketMessage.<Long>builder()
                .type(WebSocketMessageType.MESSAGE_READ)
                .senderId(currentUserId)
                .receiverId(friendId)
                .data(friendId)
                .timestamp(System.currentTimeMillis())
                .build();

        // 4. 发送已读通知
        messageProducer.sendMessageReadNotification(wsMessage);
    }

    /**
     * 撤回消息
     *
     * @param messageId 消息ID
     */
    @Override
    @Transactional
    public void recallMessage(Long messageId) {
        // 1. 获取当前用户
        User currentUser = userService.getCurrentUser();
        Long currentUserId = currentUser.getId();

        // 2. 获取消息
        PrivateMessage message = getById(messageId);
        if (message == null) {
            throw new BusinessException(ResultCode.MESSAGE_NOT_FOUND, MessageConstants.Message.MESSAGE_NOT_FOUND);
        }

        // 3. 检查权限
        if (!message.getSenderId().equals(currentUserId)) {
            throw new BusinessException(ResultCode.FORBIDDEN, MessageConstants.Message.NO_PERMISSION_RECALL);
        }

        // 4. 更新消息状态
        message.setStatus(2); // 2:已删除
        updateById(message);

        // 5. 构建WebSocket消息
        WebSocketMessage<Long> wsMessage = WebSocketMessage.<Long>builder()
                .type(WebSocketMessageType.MESSAGE_RECALL)
                .senderId(currentUserId)
                .receiverId(message.getReceiverId())
                .data(messageId)
                .timestamp(System.currentTimeMillis())
                .build();

        // 6. 发送撤回通知
        messageProducer.sendMessageRecallNotification(wsMessage);
    }
}